package system

import (
	"context"
	"encoding/json"
	"fmt"
	"gf-assistant/internal/common/factory"
	"gf-assistant/internal/system/parameter"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/gconv"
	"reflect"
	"strings"
)

type UserDao struct{}

func init() {
	userDao := UserDao{}
	factory.Put(reflect.TypeOf(userDao).String(), &userDao)
}

// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *UserDao) DB() gdb.DB {
	return g.DB()
}
func (dao *UserDao) GetUserByUserName(ctx context.Context, userName string) (res *parameter.LoginUserDO) {

	db := g.DB()
	sql := "select t.USER_ID as UserId,t.USER_NAME as UserName,t.NICK_NAME as NickName,t.PASSWORD as Password,t.PWD_SALT as pwdSalt,t.ENABLE_STATUS as EnableStatus from SYS_USER t where t.USER_NAME = ?"
	one, err := db.GetOne(ctx, sql, userName)
	if err != nil || one == nil {
		return res
	}
	err = json.Unmarshal([]byte(one.Json()), &res)
	if err != nil {
		fmt.Println("JSON unmarshal error:", err)
	}
	return res
}
func (dao *UserDao) GetUser(ctx context.Context, req *parameter.GetUserReq) (res *parameter.GetUserRes) {

	db := g.DB()
	sql := `
		  select t.USER_ID as UserId,t.USER_NAME as UserName,t.NICK_NAME as NickName,t.PASSWORD as Password,
		         t.PWD_SALT as PwdSalt,t.ENABLE_STATUS as EnableStatus ,ELT(FIELD(t.ENABLE_STATUS, 0, 1),'无效','有效')AS EnableStatusName,
		         c.NICK_NAME as CreatedUserName,p.NICK_NAME as UpdatedUserName,
				 DATE_FORMAT(t.CREATE_TIME,'%Y-%m-%d %T') as CreatedTime,
				 DATE_FORMAT(t.UPDATE_TIME,'%Y-%m-%d %T') as UpdatedTime,
				 t.ORG_ID as OrgId,o.ORG_NAME as OrgName
		  from SYS_USER t 
		  left join SYS_USER c on t.CREATE_USER=c.USER_ID
		  left join ORG_INFO o on t.ORG_ID=o.ORG_ID
		  left join SYS_USER p on t.UPDATE_USER=p.USER_ID
		  where t.USER_ID = ?`
	one, err := db.GetOne(ctx, sql, req.UserId)
	if err != nil || one == nil {
		return res
	}
	err = json.Unmarshal([]byte(one.Json()), &res)
	if err != nil {
		fmt.Println("JSON unmarshal error:", err)
	}
	return res
}

func (dao *UserDao) ListUser(ctx context.Context, req *parameter.ListUserReq) (users []*parameter.GetUserRes) {
	parameters := make([]interface{}, 0)
	sql := `
		  select t.USER_ID as UserId,t.USER_NAME as UserName,t.NICK_NAME as NickName,t.PASSWORD as Password,
		         t.PWD_SALT as PwdSalt,t.ENABLE_STATUS as EnableStatus ,ELT(FIELD(t.ENABLE_STATUS, 0, 1),'无效','有效')AS EnableStatusName,
		         c.NICK_NAME as CreatedUserName,p.NICK_NAME as UpdatedUserName,
				 DATE_FORMAT(t.CREATE_TIME,'%Y-%m-%d %T') as CreatedTime,
				 DATE_FORMAT(t.UPDATE_TIME,'%Y-%m-%d %T') as UpdatedTime,
				 t.ORG_ID as OrgId,o.ORG_NAME as OrgName,
				 r.ROLE_NAMES as RoleNames
		  from SYS_USER t 
		  left join ORG_INFO o on t.ORG_ID=o.ORG_ID
		  left join(
		      select ur.USER_ID,GROUP_CONCAT(r.ROLE_NAME) as ROLE_NAMES
			  from SYS_ROLE r 
			  join  SYS_USER_ROLE ur on ur.ROLE_ID=r.ROLE_ID and ur.ENABLE_STATUS=1
			  where r.ENABLE_STATUS=1
			  group by ur.USER_ID
		  )r on t.USER_ID=r.USER_ID
		  left join SYS_USER c on t.CREATE_USER=c.USER_ID
		  left join SYS_USER p on t.UPDATE_USER=p.USER_ID
		  where 1=1 
		  `
	if req.OrgName != "" {
		sql = sql + " and o.ORG_NAME like ? \n"
		parameters = append(parameters, "%"+strings.TrimSpace(req.OrgName)+"%") //机构名称
	}
	if req.UserName != "" {
		sql = sql + " and t.USER_NAME like ? \n"
		parameters = append(parameters, "%"+strings.TrimSpace(req.UserName)+"%")
	}

	if req.NickName != "" {
		sql = sql + " and t.NICK_NAME like ? \n"
		parameters = append(parameters, "%"+strings.TrimSpace(req.NickName)+"%")
	}
	if req.EnableStatus > -1 {
		sql = sql + " and t.ENABLE_STATUS=?\n"
		parameters = append(parameters, req.EnableStatus) //父机构
	}
	sql = sql + " order by t.ENABLE_STATUS desc, t.UPDATE_TIME DESC \n"
	sql = sql + " limit " + gconv.String((req.Page-1)*req.Size) + "," + gconv.String(req.Size)
	resultList, err := g.DB().GetAll(ctx, sql, parameters)
	if err != nil {
		fmt.Printf("query faied, error:[%v]", err.Error())
		return
	}
	//遍历结构体切片
	for _, v := range resultList {
		user := parameter.GetUserRes{}
		err = json.Unmarshal([]byte(v.Json()), &user)
		if err != nil {
			fmt.Println("JSON unmarshal error:", err)
		}
		users = append(users, &user)
	}
	return users
}
func (dao *UserDao) CountUser(ctx context.Context, req *parameter.ListUserReq) (count int64) {
	parameters := make([]interface{}, 0)
	sql := `
		  select count(t.USER_ID) userCount
		  from SYS_USER t 
		  left join ORG_INFO o on t.ORG_ID=o.ORG_ID
		  where 1=1
		  `
	if req.OrgName != "" {
		sql = sql + " and o.ORG_NAME like ? \n"
		parameters = append(parameters, "%"+strings.TrimSpace(req.OrgName)+"%") //机构名称
	}
	if req.UserName != "" {
		sql = sql + " and t.USER_NAME like ? \n"
		parameters = append(parameters, "%"+strings.TrimSpace(req.UserName)+"%")
	}

	if req.NickName != "" {
		sql = sql + " and t.NICK_NAME like ? \n"
		parameters = append(parameters, "%"+strings.TrimSpace(req.NickName)+"%")
	}
	if req.EnableStatus > -1 {
		sql = sql + " and t.ENABLE_STATUS=?\n"
		parameters = append(parameters, req.EnableStatus) //父机构
	}
	sql = sql + " order by t.ENABLE_STATUS desc, t.UPDATE_TIME DESC \n"
	sql = sql + " limit " + gconv.String((req.Page-1)*req.Size) + "," + gconv.String(req.Size)
	one, err := g.DB().GetOne(ctx, sql, parameters)
	if err != nil {
		fmt.Printf("query faied, error:[%v]", err.Error())
		return
	}
	count = gconv.Int64(one.Map()["userCount"])
	return count
}
func (dao *UserDao) CreateUser(tx gdb.TX, req *parameter.SaveUserReq) (res *parameter.SaveUserRes, err error) {
	sql := `
			insert into SYS_USER(ORG_ID,USER_NAME,NICK_NAME,PASSWORD,PWD_SALT,ENABLE_STATUS,CREATE_TIME,CREATE_USER,UPDATE_TIME,UPDATE_USER)
			values (?,?,?,?,?,?,now(),?,now(),?)
		  `
	result, err := tx.Exec(sql, req.OrgId, req.UserName, req.NickName, req.Password, req.GetPwdSalt(), req.EnableStatus, req.GetOperatorId(), req.GetOperatorId())
	if err != nil {
		fmt.Printf("insert user faied, error:[%v]", err.Error())
		return nil, err
	}
	insertId, err := result.LastInsertId()
	return &parameter.SaveUserRes{UserId: gconv.Uint(insertId)}, err
}

func (dao *UserDao) UpdateUser(tx gdb.TX, req *parameter.SaveUserReq) (res *parameter.SaveUserRes, err error) {
	parameters := make([]interface{}, 0)
	sql := `
			update SYS_USER set 
				ORG_ID=?,
				USER_NAME=?,
				NICK_NAME=?,
				ENABLE_STATUS=?,
				UPDATE_TIME=now(),
				UPDATE_USER=?
		  `
	parameters = append(parameters, req.OrgId, req.UserName, req.NickName, req.EnableStatus, req.GetOperatorId()) //项目成员
	if len(req.Password) > 0 {
		sql += ",PASSWORD=? \n"
		sql += ",PWD_SALT=? \n"
		parameters = append(parameters, req.Password, req.GetPwdSalt())
	}

	sql += "where USER_ID=? "
	parameters = append(parameters, req.UserId)
	_, err = tx.Exec(sql, parameters)
	if err != nil {
		fmt.Printf("update user faied, error:[%v]", err.Error())
		return nil, err
	}
	return &parameter.SaveUserRes{UserId: req.UserId}, err
}
func (dao *UserDao) DeleteUser(tx gdb.TX, req *parameter.DeleteUserReq) {
	parameters := make([]interface{}, 0)
	sql := `
			update SYS_USER set 
				ENABLE_STATUS=0,
				UPDATE_TIME=now(),
				UPDATE_USER=?
			where USER_ID=?
		  `
	parameters = append(parameters, req.GetOperatorId(), req.UserId)

	_, err := tx.Exec(sql, parameters)
	if err != nil {
		fmt.Printf("update user faied, error:[%v]", err.Error())
	}
}

func (dao *UserDao) GetUserPermission(ctx context.Context, req *parameter.GetUserPermissionReq) (res []*parameter.UserPermissionTreeRes) {
	sql := `
		  SELECT  t.ROLE_ID as Id, 0 as PId,t.ROLE_NAME as Title, t.REMARK as Remark,(CASE WHEN a.USER_ID>0 then 1 ELSE 0 end) as AuthState
		  FROM SYS_ROLE t
		  LEFT JOIN (
		      SELECT distinct ur.ROLE_ID,ur.USER_ID
		      FROM SYS_USER_ROLE ur
		  	  WHERE ur.USER_ID=?
		  	  	and ur.ENABLE_STATUS=1
		  )a on a.ROLE_ID=t.ROLE_ID
		  WHERE t.ENABLE_STATUS=1
		  ORDER BY t.ROLE_NAME 
		  `
	resultList, err := g.DB().GetAll(ctx, sql, req.UserId)
	if err != nil {
		fmt.Printf("query faied, error:[%v]", err.Error())
		return
	}
	//遍历结构体切片
	for _, v := range resultList {
		menu := parameter.UserPermissionTreeRes{}
		err = json.Unmarshal([]byte(v.Json()), &menu)
		if err != nil {
			fmt.Println("JSON unmarshal error:", err)
		}
		res = append(res, &menu)
	}
	return res
}
func (dao *UserDao) SaveUserRole(tx gdb.TX, UserId uint, RoleIds []uint, operatorId uint) {
	sql := `
			update SYS_USER_ROLE set 
				ENABLE_STATUS=0,
				UPDATE_TIME=now(),
				UPDATE_USER=?
			where USER_ID=?
		  `
	_, err := tx.Exec(sql, operatorId, UserId)
	if err != nil {
		fmt.Printf("insert user_role faied, error:[%v]", err.Error())
	}
	sql = `
		insert into SYS_USER_ROLE(USER_ID,ROLE_ID,ENABLE_STATUS,CREATE_TIME,CREATE_USER,UPDATE_TIME,UPDATE_USER)
		values (?,?,1,now(),?,now(),?)
		on duplicate key update 
			ENABLE_STATUS=1,
			UPDATE_TIME=now(),
			UPDATE_USER=?
	  `
	for _, v := range RoleIds {
		if v == 0 {
			continue
		}
		_, err = tx.Exec(sql, UserId, v, operatorId, operatorId, operatorId)
		if err != nil {
			fmt.Printf("insert user-role faied, error:[%v]", err.Error())
		}
	}
}
